/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import worker, { MessageEvents } from '@ohos.worker';
import ArrayList from '@ohos.util.ArrayList';
import { Log } from '../../utils/Log';
import { Constants } from './Constants';
import { WifiDeviceManager } from '../../model/common/WifiManager';
import fs from '@ohos.file.fs'
import { FileReadOption } from './FileReadOption';


const TAG = 'WorkerThreadPool'

// 跨模块调用worker路径前缀
const crossModulePathPrefix: string = '@bundle:com.ohos.photos/';
const PHONE_ENTRY_NAME: string = "phone_photos";
const PC_ENTRY_NAME: string = "pc_photos";

/**
 * 自定义worker线程池，负责worker线程的创建、启动、销毁
 */
export class WorkerThreadPool {
  public static readonly CAPACITY: number = 3;
  private static workerThreadPoolInstance: WorkerThreadPool;
  private workerList: ArrayList<worker.ThreadWorker> = new ArrayList();

  private constructor() {
  }

  public static getInstance(): WorkerThreadPool {
    if (!this.workerThreadPoolInstance) {
      Log.info(TAG, 'single instance create')
      this.workerThreadPoolInstance = new WorkerThreadPool();
    }
    return this.workerThreadPoolInstance;
  }

  /**
   * 创建worker
   * @param relativePath  worker.ts文件所在的相对路径
   * @param deviceType    设备类型，对应不同entryName (phone, pc)
   */
  public static createWorker(relativePath: string, deviceType: string): worker.ThreadWorker {
    Log.info(TAG, 'create worker, relativePath: ' + relativePath);
    // let entryName = deviceType == Constants.DEFAULT_DEVICE_TYPE ? PHONE_ENTRY_NAME : PC_ENTRY_NAME;
    let entryName = PHONE_ENTRY_NAME
    let workerInstance: worker.ThreadWorker;
    try {
      workerInstance = new worker.ThreadWorker(crossModulePathPrefix + entryName + relativePath);
    } catch (err) {
      Log.error(TAG, 'create worker instance failed' + err);
    }
    return workerInstance;
  }

  /**
   * 启动一个worker
   * @param worker  worker对象
   * @param buffer  传入worker的buffer
   * @param excFunc 主线程回调函数
   * @param name    worker名称
   */
  public static startWorker(worker: worker.ThreadWorker, path: string, size: number, callback: Function, name: string): void {
    if (!worker) {
      Log.error(TAG, 'worker' + name + 'is null');
    }
    let file = fs.openSync(path, fs.OpenMode.READ_WRITE);
    let data: ArrayBuffer = new ArrayBuffer(size)
    fs.readSync(file.fd, data);

    // while (option.offset < size) {
    //   try {
    //     let data: ArrayBuffer = new ArrayBuffer(1024 * 1)
    //     let length: number = fs.readSync(file.fd, data, option);
    //     if (length > 0) {
    //       console.info(`read file data succeed: offset=${option.offset} length=${length},`);
    //       // await this.sendToServer(data)
    //       WifiDeviceManager.getInstance().sendToServer(data)
    //       option.offset = option.offset + length
    //     }
    //     if(option.offset >= size) {
    //       fs.close(file.fd)
    //       AppStorage.setOrCreate('receivedState', 6)
    //       worker.postMessage('传输结束');
    //     }
    //   }
    //   catch (err) {
    //     console.error("read file data failed");
    //   }
    // }
    worker.postMessage(data);
    worker.onmessage = function (e: MessageEvents) {
      callback(e, name);
      Log.info(TAG, 'worker onmessage end, terminate')
      worker.terminate();
    }
    worker.onexit = function () {
      Log.debug(TAG, 'worker' + name + 'exit');
    }
  }

  /**
   * 终止worker运行
   * @param worker
   */
  public static terminateWorker(worker: worker.ThreadWorker) {
    Log.info(TAG, 'terminate worker')
    if (!worker) {
      Log.error(TAG, 'worker is null');
    }
    try {
      worker.terminate();
    } catch (err) {
      Log.error(TAG, 'worker terminate error: ' + JSON.stringify(err));
    }
  }

  /**
   * 最大容量
   */
  public capacity(): number {
    return WorkerThreadPool.CAPACITY;
  }

  /**
   * 执行workerList中的worker
   * @param path                   worker.ts文件路径
   * @param data                   处理的数据
   * @param byteLengthOfOneGroup   需要以组为单位处理的数据，例如直方图的RGBA像素统计，一组4个字节，该值为4
   * @param excFunc                主线程回调函数，用于worker结果的数据汇总
   */
  public run(path: string, Path: string, size: number, mainThreadCallback: Function) {
    let deviceType: string = AppStorage.get('deviceType');
    let workerInstance = WorkerThreadPool.createWorker(path, deviceType);
    this.workerList.add(workerInstance);
    WorkerThreadPool.startWorker(workerInstance, Path, size, mainThreadCallback, 'worker instance');
  }

  /**
   * 终止WorkerThreadPool的所有worker
   */
  public stop(): void {
    this.workerList.forEach((workerInstance, index) => {
      Log.info(TAG, 'worker ' + index + ' terminate.')
      WorkerThreadPool.terminateWorker(workerInstance);
    });
    this.workerList.clear();
  }
}